%{
#include "generate.h"

#define rac	reg_allocate
#define rgs	reg_get_string
#define rgn	reg_get_name
#define rfn	reg_fetch_by_name
#define rl	reg_load
#define rf	reg_free
#define ral1	reg_allocate_load1
#define ral2	reg_allocate_load2
#define ralm2	reg_allocate_load_move2
#define rn(a)	rgs(rgn(a))

extern reg_t reg_target;
%}
%term OP_ADD=2 OP_MUL=3 OP_UN_NEG=4 OP_ARR=5 OP_ARR_ADDR=6 OP_NEQ=7 OP_LESS=8 OP_CALL=9 OP_CALL_VOID=10 OP_ARG=11 OP_ARG_NIL=12 TERM_ID=13 TERM_CONST=14
%start head
%%

head:	expr				# 0 # if(reg_target == ANY) { reg_target = rgn(n->reg_id); /*printf("\x23 setting reg_target to %s\n", rn(n->reg_id));*/ };

expr:	reg				# 1 # rl(n->reg_id, reg_target);
expr:	OP_ADD(reg, reg)		# 2 # n->reg_id = ralm2(reg_target, LC(n)->reg_id, ANY, RC(n)->reg_id, ANY); code("\t addq %s, %s\n", rn(RC(n)->reg_id), rn(n->reg_id)); rf(LC(n)->reg_id); rf(RC(n)->reg_id);
expr:	OP_MUL(reg, reg)		# 2 # n->reg_id = ralm2(reg_target, LC(n)->reg_id, ANY, RC(n)->reg_id, ANY); code("\t imulq %s, %s\n", rn(RC(n)->reg_id), rn(n->reg_id)); rf(LC(n)->reg_id); rf(RC(n)->reg_id);
expr:	OP_UN_NEG(reg)			# 2 # n->reg_id = ral1(reg_target, LC(n)->reg_id, ANY); code("\t movq %s, %s\n\t neg %s\n", rn(LC(n)->reg_id), rn(n->reg_id), rn(n->reg_id)); rf(LC(n)->reg_id);
expr:	OP_ARR(reg, reg)		# 2 # n->reg_id = ral2(reg_target, LC(n)->reg_id, ANY, RC(n)->reg_id, ANY); code("\t leaq 0(%s, %s, 8), %s\n\t movq (%s), %s\n", rn(LC(n)->reg_id), rn(RC(n)->reg_id), rn(n->reg_id), rn(n->reg_id), rn(n->reg_id)); rf(LC(n)->reg_id); rf(RC(n)->reg_id);
expr:	OP_ARR_ADDR(reg, reg)		# 2 # n->reg_id = ral2(reg_target, LC(n)->reg_id, ANY, RC(n)->reg_id, ANY); code("\t leaq 0(%s, %s, 8), %s\n", rn(LC(n)->reg_id), rn(RC(n)->reg_id), rn(n->reg_id)); rf(LC(n)->reg_id); rf(RC(n)->reg_id);
expr:	con				# 1 # n->reg_id = rac(reg_target); code("\t movq $%ld, %s\n", n->gen_val, rn(n->reg_id));

c_nest:	OP_CALL(arg)			# 1 # n->reg_id = rac(RAX); generate_code_fix_sp(generate_code_mov_free_args(LC(n), 1)); code("\t call %s\n", n->data.child[0]->data.id.name);
arg:	OP_ARG(reg, arg)		# 2 # rl(LC(n)->reg_id, ANY); n->reg_id = reg_arg_allocate(rgn(LC(n)->reg_id)); //code("\t \x23 arg %s is %ld %ld\n", LC(n)->data.child[0]->data.id.name, n->reg_id, LC(n)->reg_id);
arg:	OP_ARG(c_nest, arg)		# 0 # n->reg_id = reg_arg_allocate(rgn(LC(n)->reg_id));
arg:	OP_ARG(OP_CALL_VOID, arg)	# 1 # n->reg_id = reg_arg_allocate(RAX); code("\t call %s\n", LC(n)->data.child[0]->data.id.name);
arg:	OP_ARG_NIL			# 0 # reg_save_caller_saved(); //code("\t \x23 matched arg_nil\n");
arg:	reg				# 0 # 

reg:	OP_CALL_VOID			# 1 # n->reg_id = rac(RAX); code("\t call %s\n", n->data.child[0]->data.id.name); reg_load_caller_saved();
reg:	OP_CALL(arg)			# 1 # n->reg_id = rac(RAX); generate_code_fix_sp(generate_code_mov_free_args(LC(n), 1)); code("\t call %s\n", n->data.child[0]->data.id.name); reg_load_caller_saved();
reg:	OP_ADD(reg, reg)		# 2 # n->reg_id = ralm2(ANY, LC(n)->reg_id, ANY, RC(n)->reg_id, ANY); code("\t addq %s, %s\n", rn(RC(n)->reg_id), rn(n->reg_id)); rf(LC(n)->reg_id); rf(RC(n)->reg_id);
reg:	OP_MUL(reg, reg)		# 3 # n->reg_id = ralm2(ANY, LC(n)->reg_id, ANY, RC(n)->reg_id, ANY); code("\t imulq %s, %s\n", rn(RC(n)->reg_id), rn(n->reg_id)); rf(LC(n)->reg_id); rf(RC(n)->reg_id);
reg:	OP_UN_NEG(reg)			# 2 # n->reg_id = ral1(ANY, LC(n)->reg_id, ANY); code("\t movq %s, %s\n\t neg %s\n", rn(LC(n)->reg_id), rn(n->reg_id), rn(n->reg_id)); rf(LC(n)->reg_id);
reg:	OP_ARR(reg, reg)		# 2 # n->reg_id = ral2(ANY, LC(n)->reg_id, ANY, RC(n)->reg_id, ANY); code("\t leaq 0(%s, %s, 8), %s\n\t movq (%s), %s\n", rn(LC(n)->reg_id), rn(RC(n)->reg_id), rn(n->reg_id), rn(n->reg_id), rn(n->reg_id)); rf(LC(n)->reg_id); rf(RC(n)->reg_id);
reg:	OP_ARR_ADDR(reg, reg)		# 2 # n->reg_id = ral2(ANY, LC(n)->reg_id, ANY, RC(n)->reg_id, ANY); code("\t leaq 0(%s, %s, 8), %s\n", rn(LC(n)->reg_id), rn(RC(n)->reg_id), rn(n->reg_id)); rf(LC(n)->reg_id); rf(RC(n)->reg_id);

reg:	TERM_ID				# 1 # n->reg_id = rfn(n->data.child[0]->data.id.name); //code("\t \x23 var %s id %ld\n", n->data.child[0]->data.id.name, n->reg_id);
reg:	con				# 1 # n->reg_id = rac(ANY); code("\t movq $%ld, %s\n", n->gen_val, rn(n->reg_id));
reg:	TERM_CONST			# 1 # n->reg_id = rac(ANY); code("\t movq $%ld, %s\n", n->data.child[0]->data.num.val, rn(n->reg_id));
con:	OP_ADD(con, con)		# 0 # n->gen_val = LC(n)->gen_val+RC(n)->gen_val; //code("\t \x23 addc %ld + %ld = %ld\n", LC(n)->gen_val, RC(n)->gen_val, n->gen_val);
con:	OP_MUL(con, con)		# 0 # n->gen_val = LC(n)->gen_val*RC(n)->gen_val; //code("\t \x23 mulc %ld * %ld = %ld\n", LC(n)->gen_val, RC(n)->gen_val, n->gen_val);
con:	OP_UN_NEG(con)			# 0 # n->gen_val = -LC(n)->gen_val; //code("\t \x23 negc %ld\n", n->gen_val);
con:	TERM_CONST			# 0 # n->gen_val = n->data.child[0]->data.num.val; //code("\t \x23 const %ld\n", n->gen_val);

%%
